﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace ExpressionTreeLib.ViewModels
{
    [ExpressionType(typeof(ConstantExpression))]
    public class ConstantViewModel : NodeViewModel
    {

        private Type _valueType;
        [TypeConverter(typeof(TypeTypeConverter))]
        public Type ValueType
        {
            get { return _valueType; }
            set { _valueType = value; this.NotifyOfPropertyChange(()=>ValueType); }
        }

        private string _value;
        public string Value
        {
            get { return _value; }
            set { _value = value; this.NotifyOfPropertyChange(()=>Value); }
        }

        public override void LoadExpressionNode(Expression expression)
        {
            base.LoadExpressionNode(expression);
            
            var constantExpression = expression as ConstantExpression;
            this._value = constantExpression.Value.ToString();
            this._valueType = constantExpression.Type;
        }

        protected override Expression CreateExpression()
        {
            var converter = TypeDescriptor.GetConverter(ValueType);
            var canConvert = converter.CanConvertFrom(typeof (string));
            if( canConvert )
                return Expression.Constant(converter.ConvertFromInvariantString(this.Value), this.ValueType);

            throw new ApplicationException("Can't convert from string to " + this.ValueType.Name);
        }

        public override void GenerateCode(StringBuilder stringBuilder)
        {
            if (this.ValueType.Equals(typeof(string)))
                stringBuilder.AppendFormat("Expression.Constant(\"{0}\", typeof({1}))", this.Value, this.ValueType.FullName);
            else if (this.ValueType.Equals(typeof(char)))
                stringBuilder.AppendFormat("Expression.Constant('{0}', typeof({1}))", this.Value, this.ValueType.FullName);
            else
                stringBuilder.AppendFormat("Expression.Constant({0}, typeof({1}))", this.Value, this.ValueType.FullName);
        }
    }
}
